package com.kakarote.oa.controller;


import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.collection.ListUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONObject;
import com.kakarote.common.log.annotation.OperateLog;
import com.kakarote.common.log.entity.OperationLog;
import com.kakarote.common.log.entity.OperationResult;
import com.kakarote.common.log.enums.ApplyEnum;
import com.kakarote.common.log.enums.BehaviorEnum;
import com.kakarote.common.log.enums.OperateObjectEnum;
import com.kakarote.core.common.ApiExplain;
import com.kakarote.core.common.Result;
import com.kakarote.core.entity.BasePage;
import com.kakarote.core.exception.CrmException;
import com.kakarote.core.feign.admin.entity.ExamineEmailBO;
import com.kakarote.core.feign.crm.entity.ExamineField;
import com.kakarote.core.feign.examine.entity.ExamineConditionDataBO;
import com.kakarote.core.feign.examine.entity.ExamineFlowFieldUpdateLogBO;
import com.kakarote.core.feign.examine.entity.ExamineInfoVo;
import com.kakarote.core.feign.examine.entity.ExamineUpdateFieldBO;
import com.kakarote.core.feign.examine.service.ExamineService;
import com.kakarote.core.utils.ExcelParseUtil;
import com.kakarote.core.utils.UserUtil;
import com.kakarote.oa.common.OaCodeEnum;
import com.kakarote.oa.entity.BO.AuditExamineBO;
import com.kakarote.oa.entity.BO.ExamineExportBO;
import com.kakarote.oa.entity.BO.ExaminePageBO;
import com.kakarote.oa.entity.BO.GetExamineFieldBO;
import com.kakarote.oa.entity.PO.OaExamine;
import com.kakarote.oa.entity.PO.OaExamineCategory;
import com.kakarote.oa.entity.PO.OaExamineField;
import com.kakarote.oa.entity.VO.ExamineVO;
import com.kakarote.oa.entity.VO.OaExamineVO;
import com.kakarote.oa.service.IOaExamineFieldService;
import com.kakarote.oa.service.IOaExamineService;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import javax.validation.constraints.NotNull;
import java.util.*;

/**
 * <p>
 * 审批表 前端控制器
 * </p>
 *
 * @author wyq
 * @since 2020-05-15
 */
@RestController
@RequestMapping("/oaExamine")
@Slf4j
public class OaExamineController {

    @Resource  IOaExamineService oaExamineService;
    @Resource  IOaExamineFieldService examineFieldService;
    @Resource  ExamineService examineService;

    @ApiExplain("获取指定的审批的关联信息")
    @PostMapping("/getRelationById")
    public Result<Map<Integer, Set<Long>>> getRelationById(@RequestParam("oaExamineId") Long oaExamineId) {
        Map<Integer, Set<Long>> map = oaExamineService.getRelation(oaExamineId);
        return Result.ok(map);
    }


    @ApiOperation("我发起的审批")
    @PostMapping("/myInitiate")
    public Result<BasePage<ExamineVO>> myInitiate(@RequestBody ExaminePageBO examinePageBO) {
        BasePage<ExamineVO> page = oaExamineService.myInitiate(examinePageBO);
        return Result.ok(page);
    }


    @ApiOperation("我审批的")
    @PostMapping("/myOaExamine")
    public Result<BasePage<ExamineVO>> myOaExamine(@RequestBody ExaminePageBO examinePageBO) {
        BasePage<ExamineVO> page = oaExamineService.myOaExamine(examinePageBO);
        return Result.ok(page);
    }

    @ApiExplain("获取指定的审批信息")
    @PostMapping("/getOaExamineById")
    public Result<ExamineVO> getOaExamineById(@RequestParam("oaExamineId") Long oaExamineId) {
        ExamineVO examineVO = oaExamineService.getOaExamineById(oaExamineId);
        return Result.ok(examineVO);
    }

    @ApiExplain("获取指定的审批信息集合")
    @PostMapping("/getOaExamineMapByIds")
    public Result<Map<Long,ExamineVO>> getOaExamineMapByIds(@RequestParam("oaExamineIds") List<Long> oaExamineIds) {
        Map<Long, ExamineVO> oaMap = oaExamineService.getOaExamineMapByIds(oaExamineIds);
        return Result.ok(oaMap);
    }

    @ApiOperation("查询详情或比编辑字段")
    @PostMapping("/getField")
    public Result<List> getField(@RequestBody GetExamineFieldBO getExamineFieldBO) {
        if (StrUtil.isNotEmpty(getExamineFieldBO.getType())) {
            return Result.ok(oaExamineService.getField(getExamineFieldBO));
        }
        return Result.ok(oaExamineService.getFormPositionField(getExamineFieldBO));
    }


    @PostMapping("/setOaExamine")
    @ApiOperation("创建审批")
    @OperateLog(apply = ApplyEnum.OA, object = OperateObjectEnum.OA_EXAMINE_MANAGE)
    public Result setOaExamine(@RequestBody JSONObject jsonObject) {
        OperationLog operationLog = oaExamineService.setOaExamine(jsonObject);
        return OperationResult.ok(operationLog);
    }

    @PostMapping("Examine")
    @ApiOperation("审批")
    public Result auditExamine(@RequestBody AuditExamineBO auditExamineBO) {
        oaExamineService.oaExamine(auditExamineBO);
        return Result.ok();
    }

    @PostMapping("/queryOaExamineInfo/{examineId}")
    @ApiOperation("查询审批详情")
    public Result<ExamineVO> queryOaExamineInfo(@PathVariable("examineId") String examineId) {
        ExamineVO examineVO = oaExamineService.queryOaExamineInfo(examineId);
        return Result.ok(examineVO);
    }

    @PostMapping("/getOaExamineInfo")
    @ApiOperation("查询审批详情")
    public Result<ExamineVO> getOaExamineInfo(@RequestParam("examineId") String examineId) {
        ExamineVO examineVO = oaExamineService.queryOaExamineInfo(examineId);
        return Result.ok(examineVO);
    }


    @PostMapping("/queryExamineRecordList")
    @ApiOperation("查询审批步骤")
    public Result<JSONObject> queryExamineRecordList(@RequestParam("recordId") String recordId) {
        JSONObject jsonObject = oaExamineService.queryExamineRecordList(recordId);
        return Result.ok(jsonObject);
    }

    @PostMapping("/queryExamineLogList")
    @ApiOperation("查询审批历史")
    public Result<List<JSONObject>> queryExamineLogList(@RequestParam("recordId") Long recordId) {
        List<JSONObject> jsonObjects = oaExamineService.queryExamineLogList(recordId);
        return Result.ok(jsonObjects);
    }


    @PostMapping("/deleteOaExamine")
    @ApiOperation("删除审批")
    @OperateLog(apply = ApplyEnum.OA, behavior = BehaviorEnum.DELETE, object = OperateObjectEnum.OA_EXAMINE_MANAGE)
    public Result deleteOaExamine(@RequestParam("examineId") Long examineId) {
        OperationLog operationLog = oaExamineService.deleteOaExamine(examineId);
        return OperationResult.ok(operationLog);
    }

    /**
     * @author hmb
     * 查询审批步骤
     */
    @PostMapping("/queryExaminStep")
    @ApiOperation("查询审批步骤")
    public Result<OaExamineCategory> queryExaminStep(@RequestParam("categoryId") Long categoryId) {
        OaExamineCategory examineCategory = oaExamineService.queryExaminStep(categoryId);
        return Result.ok(examineCategory);
    }


    /**
     * 导出
     */
    @PostMapping("/export")
    @ApiOperation("查询审批步骤")
    public void export(@RequestBody ExamineExportBO examineExportBO, HttpServletResponse response) {
        Long categoryId = examineExportBO.getCategoryId();
        ExamineInfoVo examineInfoVo = examineService.queryExamineById(Long.valueOf(categoryId)).getData();
        examineExportBO.setCategoryId(examineInfoVo.getExamineInitId());
        Integer type = examineInfoVo.getOaType();
        List<OaExamineField> fieldList = new ArrayList<>();
        if (type == 0) {
            fieldList = examineFieldService.lambdaQuery().eq(OaExamineField::getExamineCategoryId, categoryId).list();
        }
        List<Map<String, Object>> list = oaExamineService.export(examineExportBO, examineInfoVo, fieldList);

        List<ExcelParseUtil.ExcelDataEntity> dataList = new ArrayList<>();
        dataList.add(ExcelParseUtil.toEntity("category", "审批类型"));
        dataList.add(ExcelParseUtil.toEntity("createTime", "创建日期"));
        dataList.add(ExcelParseUtil.toEntity("createUserName", "创建人"));
        dataList.add(ExcelParseUtil.toEntity("examineStatus", "状态"));
        dataList.add(ExcelParseUtil.toEntity("examineUserName", "当前审批人"));
        switch (type) {
            case 1:
                dataList.add(ExcelParseUtil.toEntity("content", "审批内容"));
                dataList.add(ExcelParseUtil.toEntity("remark", "备注"));
                break;
            case 2:
                dataList.add(ExcelParseUtil.toEntity("content", "审批内容"));
                dataList.add(ExcelParseUtil.toEntity("startTime", "开始时间"));
                dataList.add(ExcelParseUtil.toEntity("endTime", "结束时间"));
                dataList.add(ExcelParseUtil.toEntity("duration", "时长"));
                dataList.add(ExcelParseUtil.toEntity("remark", "备注"));
                break;
            case 3:
                dataList.add(ExcelParseUtil.toEntity("content", "出差事由"));
                dataList.add(ExcelParseUtil.toEntity("remark", "备注"));
                dataList.add(ExcelParseUtil.toEntity("duration", "出差总天数"));
                dataList.add(ExcelParseUtil.toEntity("vehicle", "交通工具"));
                dataList.add(ExcelParseUtil.toEntity("trip", "单程往返"));
                dataList.add(ExcelParseUtil.toEntity("startAddress", "出发城市"));
                dataList.add(ExcelParseUtil.toEntity("endAddress", "目的城市"));
                dataList.add(ExcelParseUtil.toEntity("startTime", "开始时间"));
                dataList.add(ExcelParseUtil.toEntity("endTime", "结束时间"));
                dataList.add(ExcelParseUtil.toEntity("travelDuration", "时长"));
                dataList.add(ExcelParseUtil.toEntity("description", "出差备注"));
                break;
            case 4:
                dataList.add(ExcelParseUtil.toEntity("content", "加班原因"));
                dataList.add(ExcelParseUtil.toEntity("startTime", "开始时间"));
                dataList.add(ExcelParseUtil.toEntity("endTime", "结束时间"));
                dataList.add(ExcelParseUtil.toEntity("duration", "加班总天数"));
                dataList.add(ExcelParseUtil.toEntity("remark", "备注"));
                break;
            case 5:
                dataList.add(ExcelParseUtil.toEntity("content", "差旅内容"));
                dataList.add(ExcelParseUtil.toEntity("money", "报销总金额"));
                dataList.add(ExcelParseUtil.toEntity("remark", "备注"));
                dataList.add(ExcelParseUtil.toEntity("startAddress", "出发城市"));
                dataList.add(ExcelParseUtil.toEntity("endAddress", "目的城市"));
                dataList.add(ExcelParseUtil.toEntity("startTime", "开始时间"));
                dataList.add(ExcelParseUtil.toEntity("endTme", "结束时间"));
                dataList.add(ExcelParseUtil.toEntity("traffic", "交通费"));
                dataList.add(ExcelParseUtil.toEntity("stay", "住宿费"));
                dataList.add(ExcelParseUtil.toEntity("diet", "餐饮费"));
                dataList.add(ExcelParseUtil.toEntity("other", "其他费用"));
                dataList.add(ExcelParseUtil.toEntity("travelMoney", "合计"));
                dataList.add(ExcelParseUtil.toEntity("description", "费用明细描述"));
                break;
            case 6:
                dataList.add(ExcelParseUtil.toEntity("content", "审批内容"));
                dataList.add(ExcelParseUtil.toEntity("money", "借款金额"));
                dataList.add(ExcelParseUtil.toEntity("remark", "备注"));
                break;
            case 0:
                fieldList.forEach(field -> dataList.add(ExcelParseUtil.toEntity(field.getFieldName(), field.getName())));
                break;
            default:
                break;
        }
        dataList.add(ExcelParseUtil.toEntity("relateCrmWork", "关联业务"));
        ExcelParseUtil.exportExcel(list, new ExcelParseUtil.ExcelParseService() {
            @Override
            public String getExcelName() {
                return "审批";
            }

            @Override
            public boolean isXlsx() {
                return true;
            }
        }, dataList);
    }

    @PostMapping("/transfer")
    @ApiOperation("转换审批")
    public Result<List<ExamineVO>> transfer(@RequestBody List<ExamineVO> recordList) {
        List<ExamineVO> transfer = oaExamineService.transfer(recordList);
        return Result.ok(transfer);
    }


    @ApiOperation("查询字段")
    @PostMapping("/queryExamineField")
    public Result<List<ExamineField>> queryExamineField(@RequestParam("categoryId") Long categoryId) {
        List<OaExamineField> oaExamineFields = examineFieldService.queryField(categoryId, Boolean.FALSE);
        List<ExamineField> examineFields = new ArrayList<>();
        oaExamineFields.forEach(oaExamineField -> {
            boolean isNeed = Objects.equals(oaExamineField.getIsNull(), 1) && ListUtil.toList(3, 5, 6, 9).contains(oaExamineField.getType());
            if (isNeed) {
                examineFields.add(BeanUtil.copyProperties(oaExamineField, ExamineField.class));
            }
        });
        return Result.ok(examineFields);
    }

    @ApiOperation("查询条件字段")
    @PostMapping("/queryConditionData")
    public Result<Map<String, Object>> getDataMapForNewExamine(@RequestBody ExamineConditionDataBO examineConditionDataBO) {
        return Result.ok(oaExamineService.getDataMapForNewExamine(examineConditionDataBO));
    }

    @ApiOperation("查询请假类型列表")
    @PostMapping("/queryLeaveTypeList/{fieldId}")
    Result<List<String>> queryLeaveTypeList(@PathVariable("fieldId") Long fieldId) {
        return Result.ok(oaExamineService.queryLeaveTypeList(fieldId));
    }

    @PostMapping("/updateCheckStatusByNewExamine")
    public Result<Boolean> updateCheckStatusByNewExamine(@RequestBody ExamineConditionDataBO examineConditionDataBO) {
        return Result.ok(oaExamineService.updateCheckStatusByNewExamine(examineConditionDataBO));
    }

    @ApiOperation("查询请假审批通过列表")
    @PostMapping("/queryLeaveExamineList")
    Result<List<OaExamineVO>> queryLeaveExamineList(@RequestBody Map<String, Object> map) {
        return Result.ok(oaExamineService.queryLeaveExamineList(map));
    }

    @ApiOperation("查询所有字段语言包key信息")
    @PostMapping(value = "/getAllFieldLanguageRel")
    public Result<List<Map<String, Object>>> getAllFieldLanguageRel() {
        return Result.ok(oaExamineService.getAllFieldLanguageRel());
    }

    ;


    @PostMapping("/setOaExamineDraft")
    @ApiOperation("创建审批---------草稿")
    public Result setOaExamineDraft(@RequestBody JSONObject jsonObject) {
        oaExamineService.setOaExamineDraft(jsonObject);
        return Result.ok();
    }

    @PostMapping("/getOaExamineDraft")
    @ApiOperation("获取审批---------草稿")
    public Result getOaExamineDraft(@RequestParam("examineId") Long examineId) {
        List<OaExamine> list = oaExamineService.lambdaQuery().eq(OaExamine::getExamineId, examineId).list();
        if (CollectionUtil.isNotEmpty(list)) {
            return Result.ok(list.get(0).getExamineFlowDataDraft());
        }
        return Result.ok(new JSONObject());
    }

    @PostMapping("/useExamineEmailTokenForOaExamineInfo")
    @ApiOperation("通过邮件打开的链接------获取详情")
    public Result<ExamineVO> useExamineEmailTokenForExamineInfo(@RequestParam("emailToken") @NotNull String emailToken) {
        ExamineEmailBO examineEmailBO = new ExamineEmailBO();
        examineEmailBO.setEmailToken(emailToken);
        ExamineEmailBO ExamineEmailBO = examineService.getEmailAuditValid(examineEmailBO).getData();
        //校验token
        if (ObjectUtil.isEmpty(emailToken) || ObjectUtil.isEmpty(ExamineEmailBO)) {
            return Result.error(OaCodeEnum.OA_EXAMINE_EMAIL_TOKEN_ERROR);
        }
        Long userId = ExamineEmailBO.getUserId();
        ExamineVO examineVO = new ExamineVO();
        try {
            //设置用户信息
            UserUtil.setUser(userId);
            Long examineRecordId = ExamineEmailBO.getRecordId();
            List<OaExamine> oaExamineList = oaExamineService.lambdaQuery().eq(OaExamine::getExamineRecordId, examineRecordId).list();
            if (CollectionUtil.isNotEmpty(oaExamineList)) {
                examineVO = oaExamineService.queryOaExamineInfo(oaExamineList.get(0).getExamineId().toString());
            }
        } catch (Exception e) {
            //无登录状态下清理设置的用户信息
            UserUtil.removeUser();
            return Result.error(new CrmException(3000015, "请联系系统管理员！"));
        }
        return Result.ok(examineVO);
    }

    @PostMapping("/useExamineEmailTokenForOaExaminePositionInfo")
    @ApiOperation("通过邮件打开的链接------获取标签页详情")
    public Result<List<List<OaExamineField>>> useExamineEmailTokenForOaExaminePositionInfo(@RequestParam("emailToken") @NotNull String emailToken) {
        ExamineEmailBO examineEmailBO = new ExamineEmailBO();
        examineEmailBO.setEmailToken(emailToken);
        ExamineEmailBO ExamineEmailBO = examineService.getEmailAuditValid(examineEmailBO).getData();
        //校验token
        if (ObjectUtil.isEmpty(emailToken) || ObjectUtil.isEmpty(ExamineEmailBO)) {
            return Result.error(OaCodeEnum.OA_EXAMINE_EMAIL_TOKEN_ERROR);
        }
        Long examineRecordId = ExamineEmailBO.getRecordId();
        List<OaExamine> oaExamineList = oaExamineService.lambdaQuery().eq(OaExamine::getExamineRecordId, examineRecordId).list();
        if (CollectionUtil.isNotEmpty(oaExamineList)) {
            GetExamineFieldBO getExamineFieldBO = new GetExamineFieldBO();
            getExamineFieldBO.setExamineId(oaExamineList.get(0).getExamineId());
            getExamineFieldBO.setIsDetail(1);
            return Result.ok(oaExamineService.getFormPositionField(getExamineFieldBO));
        }
        return Result.ok(null);
    }

    @PostMapping("/queryFieldInfo")
    @ApiExplain("获取字段信息")
    public Result<List<OaExamineField>> queryFieldInfo(@RequestParam("label") Integer label, @RequestParam("typeId") Long typeId) {

        GetExamineFieldBO getExamineFieldBO = new GetExamineFieldBO();
        getExamineFieldBO.setIsDetail(2);
        getExamineFieldBO.setExamineId(typeId);
        List<OaExamineField> field = oaExamineService.getField(getExamineFieldBO);
        return Result.ok(field);
    }


    @PostMapping("/updateFieldInfo")
    @ApiExplain("修改字段信息")
    public void updateFieldInfo(@RequestBody ExamineUpdateFieldBO examineUpdateFieldBO) {
        oaExamineService.updateFieldInfo(examineUpdateFieldBO);
    }

    @PostMapping("/queryExamineUpdateLog")
    public Result<List<Map<String, Object>>> queryExamineUpdateLog(@RequestBody List<ExamineFlowFieldUpdateLogBO> list) {
        return Result.ok(oaExamineService.queryExamineUpdateLog(list));
    }

    @PostMapping("/updateExamineRelId")
    @ApiExplain("更换审批关联信息ID")
    public Result updateExamineRelId(Integer type, Long oldId, Long newId) {
        oaExamineService.updateExamineRelId(type, oldId, newId);
        return Result.ok();
    }

}

